/********************************************************************************************/
/* Fullhan Technology (Shanghai) Co., Ltd.                                                  */
/* Fullhan Proprietary and Confidential                                                     */
/* Copyright (c) 2014 Fullhan Technology Group Limited and its affiliated companies         */
/********************************************************************************************/

#ifndef SEC_CIPHER_AES_H
#define SEC_CIPHER_AES_H
#if 0
#ifndef _MSC_VER
#define _MSC_VER
#if defined(_MSC_VER)
	/**
	 * \name ISO C99 fixed-size types
	 *
	 * These should be in <stdint.h>, but a few compilers lack them.
	 * \{
	 */
	typedef signed char         int8_t;
	typedef unsigned char       uint8_t;
	typedef short int           int16_t;
	typedef unsigned short int  uint16_t;
//	typedef long int            int32_t; /* _WIN64 safe */
	typedef unsigned long int   uint32_t; /* _WIN64 safe */
	typedef unsigned int		size_t;
#if 0
	#ifdef _MSC_VER
		typedef __int64              int64_t;
		typedef unsigned __int64     uint64_t;
	#else
		typedef long long            int64_t;
		typedef unsigned long long   uint64_t;
	#endif
#else 
		typedef long long            int64_t;
		typedef unsigned long long   uint64_t;
#endif
	/* \} */
#else
	/* This is the standard location. */
	#include <stdint.h>
#endif
#endif
#else
	#include <stdint.h>
	typedef unsigned int		size_t;
#endif
typedef struct BlockCipher
{
	void (*set_key)(struct BlockCipher *c, const void *key, size_t len);
	void (*enc_block)(struct BlockCipher *c, void *block);
	void (*dec_block)(struct BlockCipher *c, void *block);

	void *buf;
	uint8_t key_len;
	uint8_t block_len;
} BlockCipher;

typedef struct
{
	BlockCipher c;
	uint32_t status;
	uint8_t expkey[44*4];
} AES128_Context;

typedef struct
{
	BlockCipher c;
	uint32_t status;
	uint8_t expkey[52*4];
} AES192_Context;

typedef struct
{
	BlockCipher c;
	uint32_t status;
	uint8_t expkey[60*4];
} AES256_Context;

void AES128_init(AES128_Context *c);
void AES192_init(AES192_Context *c);
void AES256_init(AES256_Context *c);
void cipher_ecb_encrypt(BlockCipher *c, void *block);
void cipher_ecb_decrypt(BlockCipher *c, void *block);
void cipher_cbc_encrypt(BlockCipher *c, void *block);
void cipher_cbc_decrypt(BlockCipher *c, void *block);
void cipher_ctr_encrypt(BlockCipher *c, void *block);
void cipher_ctr_decrypt(BlockCipher *c, void *block);
void cipher_ofb_encrypt(BlockCipher *c, void *block);
void cipher_ofb_decrypt(BlockCipher *c, void *block);
void cipher_cfb1_encrypt(BlockCipher *c, void *block);
void cipher_cfb1_decrypt(BlockCipher *c, void *block);
void cipher_cfb8_encrypt(BlockCipher *c, void *block);
void cipher_cfb8_decrypt(BlockCipher *c, void *block);
void cipher_cfb128_encrypt(BlockCipher *c, void *block);
void cipher_cfb128_decrypt(BlockCipher *c, void *block);
void cipher_ofb1_encrypt(BlockCipher *c, void *block);
void cipher_ofb1_decrypt(BlockCipher *c, void *block);
void cipher_ofb8_encrypt(BlockCipher *c, void *block);
void cipher_ofb8_decrypt(BlockCipher *c, void *block);
void cipher_ofb128_encrypt(BlockCipher *c, void *block);
void cipher_ofb128_decrypt(BlockCipher *c, void *block);
#define AES128_stackinit() \
	({ AES128_Context *ctx = alloca(sizeof(AES128_Context)); AES128_init(ctx); &ctx->c; })

#define AES192_stackinit() \
	({ AES192_Context *ctx = alloca(sizeof(AES192_Context)); AES192_init(ctx); &ctx->c; })

#define AES256_stackinit() \
	({ AES256_Context *ctx = alloca(sizeof(AES256_Context)); AES256_init(ctx); &ctx->c; })

int AES_testSetup(void);
int AES_testRun(void);
int AES_testTearDown(void);
#ifdef __cplusplus
extern "C" {
#endif
int is_aligned(const void *addr, size_t size);
void xor_block_8(uint8_t *out, const uint8_t *in1, const uint8_t *in2, size_t len);
void xor_block_const_8(uint8_t *out, const uint8_t *in, uint8_t k, size_t len);
void xor_block_32(uint32_t *out, const uint32_t *in1, const uint32_t *in2, size_t len);
void xor_block_const_32(uint32_t *out, const uint32_t *in, uint8_t k, size_t len);
void xor_block(void *out, const void *in1, const void *in2, size_t len);
void xor_block_const(uint8_t *out, const uint8_t *in, uint8_t k, size_t len);
void lshift_block(uint8_t *out, const uint8_t *in, uint8_t shift, size_t len);
void rshift_block(uint8_t *out, const uint8_t *in, uint8_t shift, size_t len);
void or_block(uint8_t *out, const uint8_t *in1, const uint8_t *in2, size_t len);
void and_block(uint8_t *out, const uint8_t *in1, const uint8_t *in2, size_t len);
void not_block(uint8_t *out, const uint8_t *in, size_t len);
#ifdef __cplusplus
}
#endif
#define PURGE(x) \
	memset(&x, 0, sizeof(x))

#endif /* SEC_CIPHER_AES_H */
